<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Exception\Handler;

use App\Constants\ErrorCode;
use App\Exception\InternalException;
use App\Exception\InvalidRequestException;
use Hyperf\Database\Model\ModelNotFoundException;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Exception\BadRequestHttpException;
use Hyperf\HttpMessage\Exception\MethodNotAllowedHttpException;
use Hyperf\HttpMessage\Exception\NotFoundHttpException;
use Hyperf\RateLimit\Exception\RateLimitException;
use Hyperf\Validation\Request\FormRequest;
use Hyperf\Validation\ValidationException;
use Psr\Http\Message\ResponseInterface;
use Throwable;
use function Hyperf\Translation\__;

class AppExceptionHandler extends ExceptionHandler
{
    public function __construct()
    {}

    /**
     * @param Throwable $throwable
     * @param ResponseInterface $response
     * @return ResponseInterface
     */
    public function handle(Throwable $throwable, ResponseInterface $response)
    {
        if ($throwable instanceof InvalidRequestException) {
            errorLogs(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
            errorLogs($throwable->getTraceAsString());
            return failed($throwable->getMessage(), $throwable->getCode());
        } elseif ($throwable instanceof InternalException) {
            errorLogs(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
            return internalError($throwable->getMessage());
        } elseif ($throwable instanceof ModelNotFoundException) {
            errorLogs(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
            errorLogs($throwable->getTraceAsString());
            return notfound(__('message.model_not_found'));
        } elseif ($throwable instanceof NotFoundHttpException || $throwable instanceof MethodNotAllowedHttpException) {
            errorLogs(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
            return notfound();
        } elseif ($throwable instanceof ValidationException) {
            /** @var FormRequest $errors */
            $errors = $throwable->errors();
            $errorMsg = current(current($errors));
            return failed($errorMsg);
        } elseif ($throwable instanceof BadRequestHttpException) {
            return failed();
        } elseif ($throwable instanceof RateLimitException) {
            return failed(__('message.line_up'), ErrorCode::SERVER_RATE_LIMIT);
        }
        errorLogs(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
        errorLogs($throwable->getTraceAsString());
        return internalError();
    }

    /**
     * @param Throwable $throwable
     * @return bool
     */
    public function isValid(Throwable $throwable): bool
    {
        return true;
    }
}
